package com.gitee.wsl.doc.soup

import com.fleeksoft.ksoup.nodes.Document
import com.fleeksoft.ksoup.nodes.Element
import com.fleeksoft.ksoup.parser.Parser

@Suppress("TooManyFunctions")
@SkrapeItDsl
class Doc( val document: Document, override var relaxed: Boolean = false) : DomTreeElement() {
    override val element: Element
        get() = this.document

    /**
     * Get the (unencoded) text of all children of this element, including any newlines and spaces present in the
     * original.
     *
     * @return unencoded, un-normalized text
     * @see text
     */
    val wholeText: String by lazy { document.wholeText() }

    val titleText: String by lazy { document.title() }

    val anchorTags :List<Element> by lazy{document.anchorTags}

    val otherOutgoingLinks :List<String> by lazy{ document.otherOutgoingLinks }

    override val toCssSelector: String = ""

    override fun makeDefaultElement(cssSelector: String): DocElement {
        return DocElement(Element(cssSelector), this.relaxed)
    }

    override fun makeDefault(cssSelector: String, relaxed: Boolean): DocElement {
        return super.makeDefault(cssSelector, this.relaxed)
    }
}

/**
 * Anchor tags that have the href attribute
 */
val Document.anchorTags: List<Element> get() = try {
    this.getElementsByTag("a").filter { it.hasAttr("href") }
} catch (e: Throwable) {
    listOf<Element>()
}

/**
 * Other outgoing links (URLs from src tags of images, scripts, etc)
 */
val Document.otherOutgoingLinks: List<String> get() = getElementsByAttribute("src").map { it.attr("src") }


fun Document.toDocWrapper() = Doc(this)


@SkrapeItDsl
fun htmlDocument(
    /*@Language("HTML")*/ html: String,
    //charset: Charset = Charsets.UTF_8,
    //jsExecution: Boolean = false,
    baseUri: String = "",
): Doc = Parser.htmlParser().parseInput(html,  baseUri).toDocWrapper()

@SkrapeItDsl
fun <T> htmlDocument(
   /* @Language("HTML")*/ html: String,
    //charset: Charset = Charsets.UTF_8,
    //jsExecution: Boolean = false,
    baseUri: String = "",
    init: Doc.() -> T,
): T = htmlDocument(html, baseUri).init()

@SkrapeItDsl
fun xmlDocument(
   /* @Language("XML")*/ xml: String,
    baseUri: String = "",
): Doc = Parser.xmlParser().parseInput(xml,  baseUri).toDocWrapper()

@SkrapeItDsl
fun <T> xmlDocument(
    /*@Language("XML")*/ xml: String,
    baseUri: String = "",
    init: Doc.() -> T,
): T = xmlDocument(xml,baseUri).init()
